package org.example.c1;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.ClosedByInterruptException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author liu-rui
 * @date 2020/5/27 下午3:55
 * @description 可以打断阻塞在java.nio.channels.Selector的线程, 打断状态被重置为true
 * @since
 */
@Slf4j
public class Demo10 {
    public static void main(String[] args) throws InterruptedException {
        final Thread thread = new Thread(() -> {
            log.info("begin {}", Thread.currentThread().isInterrupted());
            try (Selector selector = Selector.open()) {
                try (SocketChannel socketChannel = SocketChannel.open()) {
                    socketChannel.configureBlocking(false);
                    //此处会抛出ClosedByInterruptException异常,因为SocketChannel是java.nio.channels.InterruptibleChannel实现类
                    socketChannel.connect(new InetSocketAddress(8991));
                    socketChannel.register(selector, SelectionKey.OP_CONNECT);
                    while (true) {
                        log.info("select {}", selector.select());

                        if (Thread.interrupted()) {
                            log.info("由于中断而退出");
                            return;
                        }

                        Set<SelectionKey> selectionKeys = selector.selectedKeys();

                        if (!selectionKeys.isEmpty()) {
                            final SelectionKey key = selectionKeys.iterator().next();
                            log.info(key.toString());
                        }
                        selectionKeys.clear();
                    }
                }
            } catch (ClosedByInterruptException e) {
                log.error(String.format("由于中断而退出 %s", Thread.currentThread().isInterrupted()), e);
            } catch (IOException e) {
                e.printStackTrace();
            }
            log.info("end {}", Thread.currentThread().isInterrupted());
        }, "t1");

        thread.start();
        TimeUnit.SECONDS.sleep(5);
        thread.interrupt();
    }
}
